package com.heima.common.minio;

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;


//文件操作类
@EnableConfigurationProperties({MinIOConfiguration.class})
public class MinIOFileOptionsImpl implements MinIOFileOptions {
    //客户端
    @Autowired
    MinioClient minioClient;
    //配置类，用于最后组装文件访问地址
    @Autowired
    MinIOConfiguration minIOConfig;
    //上传的文件只有：图片、html->常量写死
    public static final String FILE_TYPE_IMAGE = "image/jpeg";
    public static final String FILE_TYPE_HTML = "text/html";
    //自动生成：日期结构目录
    private final static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/yyyy/MM/dd/");

    /**
     *  上传图片
     *     客户端；
     *     文件输入流；
     *     构建文件上传对象；
     *     客户端执行上传操作；
     *     返回文件访问路径；
     * @param prefix  文件前缀 /images【桶下面的一级目录，区分文件类型】
     * @param filename  文件名 /2022/09/09/1.jpg【二级目录+文件名称，由于时间结构很规律，可以自动生成】
     * @param inputStream 文件流
     * @return
     * @throws Exception
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) throws Exception {
        // 1 客户端
        // 2 文件输入流
        // 3 构建文件路径【一级目录+动态日期+文件】->构建上传文件对象
        String path = buildPath(prefix, filename);
        PutObjectArgs putObjectArgs = buildUploadFile(inputStream, path,FILE_TYPE_IMAGE);
        // 4 客户端执行上传操作
        minioClient.putObject(putObjectArgs);
        // 5 返回访问路径
        return minIOConfig.getReadPath()+minIOConfig.getBucket()+path;
    }

    /**
     * 上传html
     *         客户端；
     *         文件输入流；
     *         构建文件上传对象；
     *         客户端执行上传操作；
     *         返回文件访问路径；
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return
     * @throws Exception
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) throws Exception {
        // 1 客户端
        // 2 文件输入流
        // 3 构建文件路径【一级目录+动态日期+文件】->构建上传文件对象
        String path = buildPath(prefix, filename);
        PutObjectArgs putObjectArgs = buildUploadFile(inputStream, path,FILE_TYPE_HTML);
        // 4 客户端执行上传操作
        minioClient.putObject(putObjectArgs);
        // 5 返回访问路径
        return minIOConfig.getReadPath()+minIOConfig.getBucket()+path;
    }

    /**
     * 文件删除
     *      客户端；
     *      构建文件删除对象；
     *      客户端执行删除操作；
     * @param pathUrl  文件全路径 "http://192.168.94.129:9000/hmtt/index/list.html"
     * @throws Exception
     *
     */
    @Override
    public void delete(String pathUrl) throws Exception {
        // 1 客户端
        // 2 构建文件删除对象
        // pathUrl="http://192.168.94.129:9000/hmtt/index/list.html"->只需要：/index/list.html
        String filePath = pathUrl.replace(minIOConfig.getReadPath() +minIOConfig.getBucket()+ "/", "");
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                .bucket(minIOConfig.getBucket())//桶，下载文件所处的一级地址
                .object(filePath)//下载文件的全路径：路径+文件名
                .build();
        // 3 客户端执行删除操作
        minioClient.removeObject(removeObjectArgs);
    }

    /**
     * 文件下载
     *      客户端；
     *      构建文件下载对象；
     *      客户端执行下载操作，并返回文件输入流；
     *      返回输入流字节
     * @param pathUrl  文件全路径 "http://192.168.94.129:9000/hmtt/index/list.html"
     * @return
     */
    @Override
    public byte[] downLoadFile(String pathUrl) throws Exception {
        // 1 创建客户端
        // 2 封装文件下载对象->bucket：上传位置【桶】、object：minio中文件具体位置
        String filePath = pathUrl.replace(minIOConfig.getReadPath() +minIOConfig.getBucket()+ "/", "");
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(minIOConfig.getBucket())//桶，下载文件所处的一级地址
                .object(filePath)//下载文件的具体位置：路径+文件名
                .build();
        // 3 客户端执行下载操作，并返回【文件输入流】
        InputStream is = minioClient.getObject(getObjectArgs);
        // 4 返回输入流【工具api可以将输入流转为字节数组】
        return  IOUtils.toByteArray(is);
    }

    public String buildPath(String prefix, String fileName) {
        StringBuffer buffer = new StringBuffer();
        //拼接一级目录
        if (!prefix.isEmpty()) {
            buffer.append(prefix);
        }
        //拼接日期结构目录+文件名
        String format = simpleDateFormat.format(new Date());
        buffer.append(format).append(fileName);
        return buffer.toString();
    }

    public PutObjectArgs buildUploadFile(InputStream inputStream,String objectPath,String fileType) throws IOException {
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .stream(inputStream, inputStream.available(), -1)
                .bucket(minIOConfig.getBucket())//桶:hmtt
                .object(objectPath)//minio中的文件路径：/images/1.jpg
                .contentType(fileType)//文件类型
                .build();
        return putObjectArgs;
    }

}

